/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.brainstretch.ejb.managers;

import java.util.EnumMap;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import org.brainstretch.ejb.session.NormalizationManager;
import org.brainstretch.models.User;
import org.brainstretch.models.actions.Rating;
import org.brainstretch.models.quizzes.Quiz;
import org.brainstretch.recommend.ProfileDimension;
import org.brainstretch.recommend.ProfileVector;
import org.brainstretch.recommend.UserProfile;

/**
 *
 * @author mrodaitis
 */
@Stateless
@LocalBean
public class RatingManager {

    @PersistenceUnit(unitName="BrainStretchPU")
    EntityManagerFactory entityManagerFactory;
    
    @EJB
    NormalizationManager normalizationManager;
    
    
    private static final double[] RATING_WEIGHTS = {-.02, -.01, .01, .02, .03};
    private static final int MIN_RATING = 1;
    private static final int MAX_RATING = 5;
    
    public void rateQuiz(User user, Quiz quiz, int rateValue){
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        if(user != null){
            user = entityManager.merge(user);
            rateValue = clamp(MIN_RATING, MAX_RATING, rateValue);            
            Rating rating = new Rating(rateValue, quiz, user);
            Rating existing = getRating(user, quiz, entityManager);
            if(existing == null){
                applyRating(user, quiz, RATING_WEIGHTS[rateValue-1]);
                entityManager.persist(rating);
            }
        }        
        entityManager.close();
    }
    
    private Rating getRating(User user, Quiz quiz, EntityManager entityManager){
        Rating rating = null;
        Query findRating = entityManager.createQuery("SELECT rating FROM Rating rating JOIN rating.user user JOIN rating.quiz quiz WHERE quiz.id = ?1 AND user.id = ?2");
        try{
            rating = (Rating)findRating.setParameter(1, quiz.getId()).setParameter(2, user.getId()).getSingleResult();
        }
        catch(Exception ex){
            //TODO do something here
        }
        return rating;
    }
    
    private int clamp(int min, int max, int value){
        value = Math.min(value, max);
        value = Math.max(value, min);
        return value;
    }

    private void applyRating(User user, Quiz quiz, double impact){
        ProfileVector quizVector = new ProfileVector(quiz.getProfile());
        EnumMap<ProfileDimension, Double> normMap = normalizationManager.getNormalizationMap();
        quizVector.normalize(normMap);
        UserProfile userProfile = user.getProfile();
        userProfile.adjustWeights(quizVector, impact);
    }
    
}
